#include <iostream>
#include <string>
#include <cassert>
#include <typeinfo>
#include <typeindex>
#include <unistd.h>
/*Any类主要是实现⼀个通⽤类型出来，在c++17和boost库中都有现成的可以使⽤，但是这⾥实现⼀下
了解其思想，这样也就避免了第三⽅库的使⽤了*/
/*⾸先Any类肯定不能是⼀个模板类，否则编译的时候 Any<int> a, Any<float>b,需要传类型作
为模板参数，也就是说在使⽤的时候就要确定其类型*/
/*这是⾏不通的，因为保存在Content中的协议上下⽂，我们在定义any对象的时候是不知道他们的协
议类型的，因此⽆法传递类型作为模板参数*/
/*因此考虑Any内部设计⼀个模板容器holder类，可以保存各种类型数据*/
/*⽽因为在Any类中⽆法定义这个holder对象或指针，因为any也不知道这个类要保存什么类型的数
据，因此⽆法传递类型参数*/
/*所以，定义⼀个基类placehoder，让holder继承于placeholde，⽽Any类保存⽗类指针即可*/
/*当需要保存数据时，则new⼀个带有模板参数的⼦类holder对象出来保存数据，然后让Any类中的⽗
类指针，指向这个⼦类对象就搞定了*/
class Any
{
public:
    Any() : _content(NULL) {}
    /*为了能够接收所有类型的对象，因此将构造函数定义为⼀个模板函数*/
    template <typename T>
    Any(const T &val) : _content(new holder<T>(val)) {}
    Any(const Any &other) : _content(other._content ? other._content->clone()
                                                    : NULL) {}
    ~Any()
    {
        if (_content)
            delete _content;
    }
    const std::type_info &type() { return _content ? _content->type() : typeid(void); }
    Any &swap(Any &other)
    {
        std::swap(_content, other._content);
        return *this;
    }
    template <typename T>
    T *get()
    {
        assert(typeid(T) == _content->type());
        return &((holder<T> *)_content)->val;
    }
    template <typename T>
    Any &operator=(const T &val)
    {
        /*为val构建⼀个临时对象出来，然后进⾏交换，这样临时对象销毁的时候，顺带原先
        保存的placeholder也会被销毁*/
        Any(val).swap(*this);
        return *this;
    }
    Any &operator=(Any other)
    {
        /*这⾥要注意形参只是⼀个临时对象，进⾏交换后就会释放，所以交换后，原先保存的
        placeholder指针也会被销毁*/
        other.swap(*this);
        return *this;
    }

private:
    /*因为模板类编译时就会确定类型，因此*/
    class placeholder
    {
    public:
        virtual ~placeholder() {}
        virtual const std::type_info &type() = 0;
        virtual placeholder *clone() = 0;
    };
    /*当前的Any类中⽆法保存所有类型的对象，或者说不能整成模板类，因此声明⼀个holder
    模板类出来使⽤holder类来管理传⼊的对象*/
    /*⽽Any类只需要管理holder对象即可*/
    template <typename T>
    class holder : public placeholder
    {
    public:
        holder(const T &v) : val(v) {}
        ~holder() {}
        const std::type_info &type() { return typeid(T); }
        placeholder *clone() { return new holder(val); }

    public:
        T val;
    };
    placeholder *_content;
};